package clock.socoolby.com.clock.net;

import android.content.Context;
import android.util.Log;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import clock.socoolby.com.clock.ClockApplication;
import clock.socoolby.com.clock.Constants;
import clock.socoolby.com.clock.net.protocol.RequestBase;
import clock.socoolby.com.clock.net.listener.RequestListener;

public final class NetworkManager {
    private static NetworkManager mInstance;
    private RequestQueue mRequestQueue;

    private DefaultRetryPolicy mRetryPolicy;

    private NetworkManager() {
        mRequestQueue = getRequestQueue();
    }

    private final static String TAG = "NetworkManager";

    public static synchronized NetworkManager getInstance() {
        if (mInstance == null) {
            mInstance = new NetworkManager();
        }
        return mInstance;
    }

    public static synchronized NetworkManager getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new NetworkManager(context);
        }
        return mInstance;
    }

    private RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue =Volley.newRequestQueue(ClockApplication.getContext());
        }
        return mRequestQueue;
    }

    private NetworkManager(Context context) {
        this.mRequestQueue =Volley.newRequestQueue(context);
    }

    private void setRequestTimeout(int ms) {
        int timeout = (ms == 0) ? DefaultRetryPolicy.DEFAULT_TIMEOUT_MS : ms;

        mRetryPolicy = new DefaultRetryPolicy(timeout,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    }

    public boolean sendRequest(RequestBase request, final RequestListener listener) {
        String url = request.getUrl();
        JSONObject requestObject = request.createRequest();

        if (url == null || url.length() == 0 || requestObject == null) {
            return false;
        }
        timber.log.Timber.d(String.format("request URL:%s \nrequest Params:%s", request.getUrl(), requestObject.toString()));
        JsonObjectRequest jsonRequest = new JsonObjectRequest(url, requestObject,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        timber.log.Timber.d("http response JsonString:" + response.toString());
                        listener.onResponse(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        timber.log.Timber.d("http request fail");
                        listener.onRequestFailed(Constants.FAIL_CODE, error.toString());
                    }
                }) {
            @Override
            protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                try {
                    String jsonString = new String(response.data,
                            HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
                    return Response.success(new JSONObject(jsonString),
                            HttpHeaderParser.parseCacheHeaders(response));
                } catch (UnsupportedEncodingException e) {
                    return Response.error(new ParseError(e));
                } catch (JSONException je) {
                    return Response.error(new ParseError(je));
                }
            }
        };
        return sendRequest(30000,jsonRequest);
    }

    public boolean sendRequest(int timeout,JsonObjectRequest jsonRequest){
        setRequestTimeout(timeout);
        jsonRequest.setRetryPolicy(mRetryPolicy);
        jsonRequest.setShouldCache(false);
        mRequestQueue.add(jsonRequest);
        return true;
    }

}
